package org.geektimes.projects.user.service.impl;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.geektimes.projects.user.domain.User;
import org.geektimes.projects.user.service.UserService;
import org.geektimes.projects.user.sql.DBConnectionManager;
import org.geektimes.projects.user.sql.LocalTransactional;
import org.geektimes.projects.user.validator.bean.validation.group.InsertGroup;
import org.geektimes.projects.user.validator.bean.validation.group.UpdateGroup;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.EntityTransaction;
import javax.persistence.Query;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import java.util.Collection;
import java.util.Objects;
import java.util.Set;
import java.util.logging.Logger;

public class UserServiceImpl implements UserService {
    private static final Logger logger = Logger.getLogger(UserServiceImpl.class.getName());

    @Resource(name = "bean/EntityManager")
    private EntityManager entityManager;

    @Resource(name = "bean/Validator")
    private Validator validator;

    @ConfigProperty(name = "application.name")
    private String applicationName;

    @Override
    // 默认需要事务
    @LocalTransactional
    public boolean register(User user) throws ConstraintViolationException {
        Set<ConstraintViolation<User>> violations = validator.validate(user, InsertGroup.class);
        if (violations.isEmpty()) {
            EntityTransaction transaction = entityManager.getTransaction();
            transaction.begin();
            // 主调用
            try {
                entityManager.persist(user);
            } catch (Exception e) {
                logger.severe(e.getMessage());
                e.printStackTrace();
                transaction.rollback();
            } finally {
                if (transaction.isActive()) {
                    transaction.commit();
                }
            }
        } else {
            throw new ConstraintViolationException(violations);
        }
        return Objects.nonNull(user.getId());
    }

    @Override
    public boolean deregister(User user) {
        return false;
    }

    @Override
    @LocalTransactional
    public boolean update(User user) {
        Set<ConstraintViolation<User>> violations = validator.validate(user, UpdateGroup.class);
        if (violations.isEmpty()) {
            EntityTransaction transaction = entityManager.getTransaction();
            transaction.begin();
            try {
                entityManager.merge(user);
            } catch (Exception e) {
                logger.severe(e.getMessage());
                e.printStackTrace();
                transaction.rollback();
            } finally {
                if(transaction.isActive()){
                    transaction.commit();
                }
            }
        } else {
            throw new ConstraintViolationException(violations);
        }
        return true;
    }

    @Override
    public User queryUserById(Long id) {
        Query query = entityManager.createQuery("select u from User u  where id = ?1");
        query.setParameter(1, id);
        return (User) query.getSingleResult();
    }

    @Override
    public User queryUserByNameAndPassword(String name, String password) {
        return null;
    }

    @Override
    public Collection<User> getAll() {
        Query nativeQuery = entityManager.createNativeQuery(DBConnectionManager.QUERY_USERS_DDL_SQL, User.class);
        return nativeQuery.getResultList();
    }

    @Override
    public String getConfigValue() {
        return applicationName;
    }
}
